package com.tech.entity

import com.tech.common.{DateUtil, SimplyDateUtil}

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object Retailevent {

  /**
   * 行为属性规则匹配
   *
   * @param map                   行为属性规则map
   * @param retailevent           事件的实体
   * @param dimDataGroupDetailMap 标签群组map
   */
  def matchRule(map: Map[String, Any],
                retaileventMap: mutable.HashMap[String, Any],
                dimDataGroupDetailMap: mutable.HashMap[String, ArrayBuffer[String]],
                columnTypeMap: mutable.HashMap[String, String]): Boolean = {

    val behaviorAttribute = map("behaviorAttribute").toString
    val behaviorAttributeSymbol = map("behaviorAttributeSymbol").toString

    columnTypeMap(behaviorAttribute) match {
      case "String" =>
        matchString(retaileventMap(behaviorAttribute).toString, map("behaviorAttributeValue").toString, behaviorAttributeSymbol)
      case "Integer" | "Double" | "Decimal" =>
        matchDouble(retaileventMap(behaviorAttribute).toString.toDouble, map, behaviorAttributeSymbol)
      case "Date" | "DateTime" =>
        matchDate(retaileventMap(behaviorAttribute).toString.toLong, map, behaviorAttributeSymbol)
      case "Dimension" =>
        matchList(retaileventMap(behaviorAttribute).toString, map, behaviorAttributeSymbol, dimDataGroupDetailMap)
      case _ =>
        false
    }


  }

  /**
   * 规则匹配
   *
   * @param eventValue              事件的值
   * @param map                     规则的map
   * @param behaviorAttributeSymbol 规则匹配的值之间的关联关系
   * @return 规则匹配的结果 bool
   */
  def matchDouble(eventValue: Double, map: Map[String, Any], behaviorAttributeSymbol: String): Boolean = {

    if (behaviorAttributeSymbol == "between") {
      val values = map("behaviorAttributeValue").toString
      val minValue = values.split(",").head.toDouble
      val maxValue = values.split(",")(1).toDouble
      matchDoubleWithBetween(eventValue, minValue, maxValue)
    } else {
      val behaviorAttributeValue = map("behaviorAttributeValue").toString.toDouble

      behaviorAttributeSymbol match {
        //eq：等于
        case "eq" => eventValue == behaviorAttributeValue
        //neq：不等于
        case "neq" => eventValue != behaviorAttributeValue
        //gt：大于
        case "gt" => eventValue > behaviorAttributeValue
        //lt：小于
        case "lt" => eventValue < behaviorAttributeValue
        //gte：大于等于
        case "gte" => eventValue >= behaviorAttributeValue
        //lte：小于等于
        case "lte" => eventValue <= behaviorAttributeValue
        //其他
        case _ =>
          println("未知的过滤条件：" + behaviorAttributeSymbol)
          false
      }
    }


  }


  /**
   * 规则匹配
   *
   * @param eventValue              事件的值
   * @param map                     规则内容map
   * @param behaviorAttributeSymbol 规则匹配的值之间的关联关系
   * @param dimDataGroupDetailMap   标签群组（仅对belong/notBelong生效）
   * @return 规则匹配的结果 bool
   */
  def matchList(eventValue: String, map: Map[String, Any], behaviorAttributeSymbol: String, dimDataGroupDetailMap: mutable.HashMap[String, ArrayBuffer[String]]): Boolean = {

    val bool = behaviorAttributeSymbol match {
      case "null" => eventValue == null
      case "notnull" => eventValue != null
      case "eq" => map("behaviorAttributeValue").asInstanceOf[List[String]].contains(eventValue)
      case "neq" => !map("behaviorAttributeValue").asInstanceOf[List[String]].contains(eventValue)
      case "belong" => dimDataGroupDetailMap(map("behaviorAttributeValue").toString).contains(eventValue)
      case "notBelong" => !dimDataGroupDetailMap(map("behaviorAttributeValue").toString).contains(eventValue)
      case _ => false
    }
    bool
  }

  /**
   * 规则匹配
   *
   * @param eventValue              事件的值Long
   * @param map                     规则内容map
   * @param behaviorAttributeSymbol 规则匹配的值之间的关联关系
   * @return 规则匹配的结果 bool
   */
  def matchDate(eventValue: Long, map: Map[String, Any], behaviorAttributeSymbol: String): Boolean = {

    val format = SimplyDateUtil.getFormat()
    val dayFormat = SimplyDateUtil.getDayFormat()

    val bool = behaviorAttributeSymbol match {
      case "eq" => eventValue == format.parse(map("behaviorAttributeValue").toString).getTime
      case "neq" => eventValue != format.parse(map("behaviorAttributeValue").toString).getTime
      case "gt" => eventValue > format.parse(map("behaviorAttributeValue").toString).getTime
      case "lt" => eventValue < format.parse(map("behaviorAttributeValue").toString).getTime
      case "between" => eventValue >= format.parse(map("behaviorAttributeValue").toString.split(",")(0)).getTime && eventValue <= format.parse(map("behaviorAttributeValue").toString.split(",")(1)).getTime
      case "yesterday" => dayFormat.format(eventValue) == DateUtil.getYesterday
      case "today" => dayFormat.format(eventValue) == DateUtil.getToday
      case "lastweek" => dayFormat.format(eventValue) >= DateUtil.getLastWeekStart && dayFormat.format(eventValue) <= DateUtil.getLastWeekEnd
      case "thisweek" => dayFormat.format(eventValue) >= DateUtil.getThisWeekStart && dayFormat.format(eventValue) <= DateUtil.getThisWeekEnd
      case "lastmonth" => dayFormat.format(eventValue) >= DateUtil.getLastMonthStart && dayFormat.format(eventValue) <= DateUtil.getLastMonthEnd
      case "thismonth" => dayFormat.format(eventValue) >= DateUtil.getThisMonthStart && dayFormat.format(eventValue) <= DateUtil.getThisMonthEnd
      case "lastyear" => dayFormat.format(eventValue) >= DateUtil.getLastYearStart && dayFormat.format(eventValue) <= DateUtil.getLastYearEnd
      case "thisyear" => dayFormat.format(eventValue) >= DateUtil.getThisYearStart && dayFormat.format(eventValue) <= DateUtil.getThisYearEnd
      case "recentlyday" => eventValue >= System.currentTimeMillis() - (map("behaviorAttributeValue").toString.toDouble * 1000).toLong * 60 * 60 * 24
      case "recentlyweek" => eventValue >= System.currentTimeMillis() - (map("behaviorAttributeValue").toString.toDouble * 1000).toLong * 60 * 60 * 24 * 7
      case "recentlymonth" => eventValue >= System.currentTimeMillis() - (map("behaviorAttributeValue").toString.toDouble * 1000).toLong * 60 * 60 * 24 * 30
      case "recentlyyear" => eventValue >= System.currentTimeMillis() - (map("behaviorAttributeValue").toString.toDouble * 1000).toLong * 60 * 60 * 24 * 365
      case _ => false
    }
    bool
  }


  /**
   * 规则匹配(String)
   *
   * @param eventValue              事件的值
   * @param behaviorAttributeValue  规则的值 String
   * @param behaviorAttributeSymbol 规则匹配的值之间的关联关系
   * @return 规则匹配的结果 bool
   */
  def matchString(eventValue: String, behaviorAttributeValue: String, behaviorAttributeSymbol: String): Boolean = {

    val bool = behaviorAttributeSymbol match {
      case "null" => eventValue == null
      case "notnull" => eventValue != null
      //eq：等于
      case "eq" => eventValue == behaviorAttributeValue
      //neq：不等于
      case "neq" => eventValue != behaviorAttributeValue
      //startwith
      case "startwith" => eventValue != null && eventValue.startsWith(behaviorAttributeValue)
      //endwith
      case "endwith" => eventValue != null && eventValue.endsWith(behaviorAttributeValue)
      //contains
      case "contains" => eventValue != null && eventValue.contains(behaviorAttributeValue)
      //notcontains：不包含
      case "notcontains" => eventValue != null && !eventValue.contains(behaviorAttributeValue)
      //其他
      case _ =>
        println("未知的过滤条件：" + behaviorAttributeSymbol)
        false
    }
    bool
  }


  /**
   * 累计满足的条件匹配
   *
   * @param eventSum    事件次数（交易事件存在其他Double型指标）的总计
   * @param limitValue  匹配条件的值
   * @param limitSymbol 匹配的比较符
   * @return 是/否
   */
  def matchLimit(eventSum: Double, limitValue: Double, limitSymbol: String): Boolean = {

    limitSymbol match {
      //eq：等于
      case "eq" => eventSum == limitValue
      //neq：不等于
      case "neq" => !(eventSum == limitValue)
      //gt：大于
      case "gt" => eventSum > limitValue
      //lt：小于
      case "lt" => eventSum < limitValue
      //gte：大于等于
      case "gte" => eventSum >= limitValue
      //lte：小于等于
      case "lte" => eventSum <= limitValue
      //其他
      case _ =>
        println("未知的过滤条件：" + limitSymbol)
        false
    }
  }

  /**
   * 累计满足的条件匹配（between）
   *
   * @param eventValue 事件次数（交易事件存在其他Double型指标）的总计
   * @param minValue   匹配条件的最小值
   * @param maxValue   匹配条件的最大值
   * @return 是/否
   */
  def matchDoubleWithBetween(eventValue: Double, minValue: Double, maxValue: Double): Boolean = {

    eventValue >= minValue && eventValue <= maxValue
  }

}